//
// Created by buyongjiu on 2024/4/24.
//

#ifndef FEI_PARSER_LR_H
#define FEI_PARSER_LR_H

#include <vector>
#include <string>
#include <map>
#include "Grammar.h"
#include "Token.h"

static int staticstate = 0;

enum Action_Type {SHIFT, REDUCE, ACC};

struct Action {
    Action_Type type;
    int num;
    // reduce中用于规约的产生式
    std::string left;
    std::vector<V *> right;
    Action(Action_Type type, int num){
        this->type = type;
        this->num = num;
    }
    Action(Action_Type type, std::string left, std::vector<V *> right){
        this->type = type;
        this->num = -1;
        this->left = left;
        this->right = right;
    }
};

struct Production_right{
    std::vector<V *> right;
    std::vector<V *> FSS;
    Production_right(std::vector<V *> right, std::vector<V *> FSS){
        this->right = right;
        this->FSS = FSS;
    }
    // 重载 ==
    bool operator==(const Production_right& other) const {
        // 使用std::equal比较两个向量的元素是否全部相等
        return (this->right.size() == other.right.size()) && (this->FSS.size() == other.FSS.size()) &&std::equal(right.begin(), right.end(), other.right.begin()) &&
               std::equal(FSS.begin(), FSS.end(), other.FSS.begin());
    }
};

struct Production{
    std::string left;
    std::vector<Production_right> right;
    Production(std::string left, std::vector<Production_right> right){
        this->left = left;
        this->right = right;
    }
};

struct LR_struct{
    int state;
    std::vector<Production> action;
    std::map<std::string, int> next_state;
    LR_struct(){
        state = staticstate++;
    }
};

class LR {
public:
    std::vector<LR_struct *> LR_table;
    std::map<std::string, V *> V_map;
    Grammar grammar;
    std::string start;
    std::map<int, std::map<std::string, int>> GOTO;
    std::map<int, std::map<std::string, Action*>> ACTION;
    std::map<int, LR_struct *> state_struct;
    void build_LR_table();
    void get_closure(LR_struct *state);
    void move(LR_struct *nowstate);
    void move_to(LR_struct *nowstate, const std::string& input);
    void addProduction(LR_struct *receive, const std::string& left, const Production_right & right);
    int compareState(LR_struct *a, LR_struct *b);
    int build_GOTO_ACTION_Table();
    int GO(int nowstate, std::string input);
    int accept(std::vector<Token> tokens);
    void print_Action();
    void print_GOTO();
    void print_Symbol_Stack(std::stack<std::string> temp_symbol_stack);
    void print_State_Stack(std::stack<int> temp_state_stack);
    LR(const Grammar& grammar){
        this->grammar = grammar;
        this->start = grammar.start + "'";
    }
};


#endif //FEI_PARSER_LR_H
